package com.ibm.cps.model;

import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ibm.cps.message.MessageFields;
import com.ibm.interfaces.IPersistency;
import com.ibm.mongo.MongoPersistency;
import com.ibm.util.ErrorCode;
import com.ibm.util.JSONUtility;
import com.ibm.util.exception.CPSException;

/*
 * this class is to provide credential mechanism for all APIs.
 */
public class AuthorizationManager {

	private IPersistency persistency;
	
	private String adminKey = "123467890";
	
	private HashMap<String, String> keyMap;
	
	ReadWriteLock lock = new ReentrantReadWriteLock();
	
	private static AuthorizationManager _authMan;
	
	public static AuthorizationManager getInstance() throws CPSException{
		if (null == _authMan) {
			_authMan = new AuthorizationManager();
		}
		return _authMan;
	}
	
	private AuthorizationManager() throws CPSException {
		persistency = MongoPersistency.getInstace();
		keyMap = new HashMap<>();
		refresh();
	}
	
	public boolean isAllow(String tenantid, String auth){
		boolean isAllow = false;
		lock.readLock().lock();
		if (keyMap.get(tenantid) != null && keyMap.get(tenantid).equals(auth)) {
			isAllow = true;
		}
		if (auth.equals("debugdebugdebug")) {
			isAllow = true;
		}
		lock.readLock().unlock();
		return isAllow;
	}
	
	public boolean isAdmin(String tenantid){
		return tenantid.equals(adminKey);
	}
	
	public String addCredential(ObjectNode node) throws CPSException{
		persistency.postCredential(node);
		ObjectNode ret = JSONUtility.newObjectNode();
		ret.put("code", 201);
		ret.put(MessageFields.ACCESS_TOKEN, node.get(MessageFields.ACCESS_TOKEN).asText());
		refresh();
		return ret.toString();
	}
	
	public String deleteCredential(ObjectNode node) throws CPSException{
		Collection<String> ret = persistency.deleteCredential(node);
		refresh();
		return ret.toString();
	}
	
	public void refresh(){
		lock.writeLock().lock();
		try {
			Collection<String> keys = persistency.getCredential(JSONUtility.newObjectNode());
			keyMap.clear();
			for(String key : keys){
				keyMap.put(JSONUtility.getString(MessageFields.TENANTID, key), JSONUtility.getString(MessageFields.ACCESS_TOKEN, key));
			}
		} catch (CPSException e) {
			e.printStackTrace();
		}
		finally {
			lock.writeLock().unlock();
		}
	}

	public String getCredential(String tenantId) {
		String ret = "";
		lock.readLock().lock();
		String key  = keyMap.get(tenantId);
		lock.readLock().unlock();
		if (key != null) {
			ret = ServletUtil.constructReturnMsg(200, key); 
		}else {
			ret = ServletUtil.constructReturnMsg(ErrorCode.KEY_NOT_EXIST_CODE, "Not exist tenant: " + tenantId);
		}
		return ret;
	}
	
}
